# this module help recv & send position data

from location_init import *
from socket import *
import threading
import time
import multiprocessing

from location_calc import LocationCalculater

SERVER_IP = '127.0.0.1'
LOCATION_PORT = 41234

class LocationServer:
    def __init__(self):
        print("__init__ LocationServer start")
        self.name = 'LocationServer'
        self.log = open(out_dir+"/log/recv-{}.txt".format(time.time()),"w")
        print("1111")

        self._code_mode = "utf-8"
        self._reply_addr = None

        self._send_msg_queue = queue.Queue(64)

        self._shutdown = False

        # creaete calculate module
        self.calculater = LocationCalculater(self) 

        # start server module
        # recv msg is main threading
        # send msg is an daemon threading 
        # self.start_udp()
        
        print("__init__ LocationServer end")

    def is_shutdown(self):
        return self._shutdown

    def set_shutdown(self):
        print("set status shutdown")
        self._shutdown = True

    def get_grd_display_info(self,sz=5):
        loc_list = self.calculater.location
        # print("1"*10)
        pos_dict_list = loc_list.get_latest_pos(sz)
        return pos_dict_list

    def get_sim_display_info(self,sz=5):
        loc_list = self.calculater.location._sim_pair
        pos_dict_list = loc_list.get_latest_pos(sz)
        return pos_dict_list

    def start_udp(self):
        self.server_socket = socket(AF_INET, SOCK_DGRAM) 
        self.server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, True)
        self.server_socket.bind((SERVER_IP, LOCATION_PORT))

        # start send msg threading
        t=threading.Thread(target=self.send_msg,args=())
        t.daemon = True 
        t.start()   

        t=threading.Thread(target=self.recv_msg,args=())
        t.daemon = True 
        t.start()   

        while True:
            if (self._shutdown): break
            time.sleep(3)


    def recv_msg(self):
        # while true - recv message, main threading
        while True:
            if (self._shutdown): break

            recv_msg = self.server_socket.recvfrom(1024)

            self._reply_addr = recv_msg[1]

            recv_msg = recv_msg[0].decode(self._code_mode) 
            print("\nMSG:",recv_msg,"\n")
            print(recv_msg,file=self.log)

            self.handle_msg(recv_msg)

    def send_msg(self):
        # while true - send message
        while True:
            if (self._reply_addr is None): continue
            
            msg = self._send_msg_queue.get()
            print(msg)
            print("#"+msg,file=self.log)
            self.server_socket.sendto(msg.encode(self._code_mode), self._reply_addr) 

    def handle_msg(self,recv_msg:str):
        if recv_msg.startswith("Initial"): return 

        tmp = recv_msg.split(' ')
        if (len(tmp)!=2):
            raise Exception("Fail to get term_id [{}]".format(recv_msg))

        term_id,elems = int(tmp[0]),tmp[1].split(',')

        data_type,data_info = elems[0],elems[1:]

        self.calculater.info_queue.put([term_id,data_type,data_info])    

    def __del__(self):
        self.log.close()
        print("__del__ LocationServer end")
        pass

    def bind_simulte_map(self,simulate_map):
        print('bind sim map succeed')
        self.calculater.bind_map = simulate_map
        self.calculater.bind_map_update()

def raise_location_server(proc_name,loc_server):
    print("Proc [{}] start".format(proc_name))
    
    # out_file = open(out_dir+"/detail.txt","w")
    # print("- proc output to file:",out_dir+"/detail.txt")
    # sys.stdout = out_file

    loc_server.start_udp()

    print("Proc [{}] end".format(proc_name))